/*
 * Copyright 2010, 2011, 2012 mapsforge.org
 *
 * This program is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 */
package com.unicampmaps;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import org.mapsforge.android.maps.MapActivity;
import org.mapsforge.android.maps.MapController;
import org.mapsforge.android.maps.MapView;
import org.mapsforge.android.maps.overlay.OverlayItem;
import org.mapsforge.core.GeoPoint;
import org.mapsforge.map.reader.header.FileOpenResult;

import android.content.Context;
import android.content.res.AssetManager;
import android.graphics.drawable.Drawable;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.widget.Toast;


public class BasicMapViewer extends MapActivity {
        private static final File MAP_FILE = new File(Environment.getExternalStorageDirectory().getPath(), "unicamp.map");
        
        public static final GeoPoint IC3 = new GeoPoint(-22.81355, -47.06386);
        public static final GeoPoint CB = new GeoPoint(-22.81737, -47.06846);
        public static final GeoPoint RU = new GeoPoint(-22.8178, -47.07233);
        
        public static final GeoPoint MAP_GEOPOINT_MIN = new GeoPoint(-22.8235600, -47.0751300);
        public static final GeoPoint MAP_GEOPOINT_MAX = new GeoPoint(-22.8120900, -47.0576800);
        
        public static final GeoPoint MAP_GEOPOINT_CENTER = new GeoPoint(-22.8178250, -47.0664050);

        public static int GPS_UPDATE_TIME = 5*1000;//5 sec
        
        public static List<Venue> venues = new ArrayList<Venue>();
        private SampleBalloonItemizedOverlay itemizedOverlay;
        private OverlayItem personOverlay;
        private MapView mapView;
        private String provider;
        private LocationManager locationManager;
        
        private final LocationListener locationListener=new LocationListener() {
            public void onLocationChanged(Location location) {
            	updateWithNewLocation(location);
            }
            public void onProviderDisabled(String provider){
            	updateWithNewLocation(null);
            }
            public void onProviderEnabled(String provider) { }
            public void onStatusChanged(String provider, int status, Bundle extras) { }
        };
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
        	super.onCreate(savedInstanceState);
        	
        	copyAssets();
        	
        	this.mapView = new MapView(this);
        	this.mapView.setClickable(true);
        	this.mapView.setBuiltInZoomControls(true);
            FileOpenResult fileOpenResult = this.mapView.setMapFile(MAP_FILE);
            if (!fileOpenResult.isSuccess()) {
                    Toast.makeText(this, fileOpenResult.getErrorMessage(), Toast.LENGTH_LONG).show();
                    finish();
            }
            
            this.itemizedOverlay = new SampleBalloonItemizedOverlay(this.mapView);
        	
            // add the ArrayItemizedOverlay to the MapView
            this.mapView.getOverlays().add(itemizedOverlay);
            
            loadMapItems();
            
            setMyLocation();

            MapController mapController = mapView.getController();
            mapController.setZoom(16);  
            setContentView(mapView);
        }
		
        public static void addVenue(Venue v) {
        	BasicMapViewer.venues.add(v);
        }
		
        public static void emptyVenues() {
        	BasicMapViewer.venues.clear();
        }
        
        private void loadMapItems() {
        	
            for (int i = 0; i < BasicMapViewer.venues.size(); i++) {
            	Venue v = BasicMapViewer.venues.get(i);
            	GeoPoint point = new GeoPoint(v.getLatitude(), v.getLongitude());
            	OverlayItem overlay = new OverlayItem(point, v.getName(), v.getAbbr());
            	if (v.getType() == VenueData.T_TRANSPORT) {
            		Drawable drawable = this.getResources().getDrawable(R.drawable.busstop);
            		drawable.setBounds(-drawable.getIntrinsicWidth()/2, -drawable.getIntrinsicHeight(), drawable.getIntrinsicWidth() /2, 0);
            		overlay.setMarker(drawable);
            	}
            	
            	this.itemizedOverlay.addOverlay(overlay);
            	
            	this.mapView.setCenter(point);
            }
        }
        
        private void setMyLocation() {
            String context = Context.LOCATION_SERVICE;
            locationManager = (LocationManager)getSystemService(context);

            Criteria criteria = new Criteria();
            criteria.setAccuracy(Criteria.ACCURACY_FINE);
            criteria.setAltitudeRequired(false);
            criteria.setBearingRequired(false);
            criteria.setCostAllowed(true);
            criteria.setPowerRequirement(Criteria.POWER_LOW);
            provider = locationManager.getBestProvider(criteria, true);
            
            //System.out.println(provider);
            if (provider != null) {
            	Location location = locationManager.getLastKnownLocation(provider);
                
                updateWithNewLocation(location);
                locationManager.requestLocationUpdates(provider, GPS_UPDATE_TIME, 10, locationListener);
            }  
        }
        
        private void updateWithNewLocation(Location location) {
            
        	if (location != null)  {
                GeoPoint geoPoint = new GeoPoint(location.getLatitude(), location.getLongitude());
                System.out.println(geoPoint);
                //geoPoint = BasicMapViewer.CB;
                
                //Só exibe o ponto no mapa se estiver dentro do recorte do nosso arquivo 
                if (geoPoint.getLatitude() > BasicMapViewer.MAP_GEOPOINT_MIN.getLatitude() &&
            		geoPoint.getLatitude() < BasicMapViewer.MAP_GEOPOINT_MAX.getLatitude() &&
            		geoPoint.getLongitude() > BasicMapViewer.MAP_GEOPOINT_MIN.getLongitude() &&
            		geoPoint.getLongitude() < BasicMapViewer.MAP_GEOPOINT_MAX.getLongitude()) {
                	
                	
                	if(personOverlay==null){
                		personOverlay = new OverlayItem(geoPoint, "Estou aqui!", "");

                		Drawable drawable = this.getResources().getDrawable(R.drawable.me_marker);
                		drawable.setBounds(-drawable.getIntrinsicWidth()/2, -drawable.getIntrinsicHeight(), drawable.getIntrinsicWidth() /2, 0);
                		personOverlay.setMarker(drawable);
                		this.itemizedOverlay.addOverlay(personOverlay);
                		this.mapView.getOverlays().add(itemizedOverlay);
                	}
	                
                	personOverlay.setPoint(geoPoint);
                	
	            	this.mapView.setCenter(geoPoint);
                }
            } else{
            	//personOverlay.setMarker(null);
            }
        }
        
        /**
         * copyAssets
         * 
         * Copia todos os arquivos na pasta "assets" para o cart�o de mem�ria do aparelho
         * Na pasta assets est� o recorte do mapa da unicamp que � utilizado pelo aplicativo
         */
        private void copyAssets() { 
    	    AssetManager assetManager = getAssets(); 
    	    String[] files = null; 
    	    try { 
    	        files = assetManager.list(""); 
    	    } catch (IOException e) { 
    	        Log.e("tag", e.getMessage()); 
    	    } 
    	    for(String filename : files) { 
    	        InputStream in = null; 
    	        OutputStream out = null; 
    	        try { 
    	          in = assetManager.open(filename); 
    	          out = new FileOutputStream(Environment.getExternalStorageDirectory().getPath() + "/" + filename); 
    	          copyFile(in, out); 
    	          in.close(); 
    	          in = null; 
    	          out.flush(); 
    	          out.close(); 
    	          out = null; 
    	        } catch(Exception e) { 
    	            Log.e("tag", e.getMessage()); 
    	        }        
    	    } 
    	} 
        
    	private void copyFile(InputStream in, OutputStream out) throws IOException { 
    	    byte[] buffer = new byte[1024]; 
    	    int read; 
    	    while((read = in.read(buffer)) != -1){ 
    	      out.write(buffer, 0, read); 
    	    } 
    	}
    	
    	@Override
    	public void onPause(){
    		super.onPause();
		    locationManager.removeUpdates(locationListener);
    	}
    	
    	@Override
    	public void onResume(){
    		super.onResume();
    		if(provider != null){
    			locationManager.requestLocationUpdates(provider, GPS_UPDATE_TIME, 0, locationListener);
    		}
    	}
}